home *** CD-ROM | disk | FTP | other *** search
- /**\
- |**| =====================================================================
- |**|
- |**| Circular Layout.c
- |**|
- |**| This file contains the calls that this sample needs to make
- |**| the QuickDraw GX shell work correctly.
- |**|
- |**| QuickDraw GX Libraries Used:
- |**| "color library.c", "font library.c", "graphics debug library.c",
- |**| "layout library.c", "shape library.c", and "transform library.c".
- |**|
- |**| ©1992-1994 Apple Computer, Inc.
- |**| All rights reserved.
- |**|
- |**| =====================================================================
- \**/
-
-
- #include "QDGX shell.h"
- #include "layout routines.h"
- #include "layout library.h"
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| PROTOTYPES
- |**| ---------------------------------------------------------------------
- \**/
-
- // funtions required by shell
-
- void DoSetup (void);
- void DoDraw (WindowPtr wind, Boolean updating);
- OSErr DoCreateNew (void);
- void DoDispose (WindowPtr wind);
- void DoIdle (WindowPtr wind);
- void DoTeardown (void);
- void DoClick (WindowPtr wind, Point p);
-
- // private functions
-
- OSErr DoWindowInit (WindowPtr wind);
- void CreateSampleImage (WindowPtr wind);
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| ENUMS
- |**| ---------------------------------------------------------------------
- \**/
- enum { rWindResource = 128 };
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| GLOBALS
- |**| ---------------------------------------------------------------------
- \**/
- // If gDebugging = TRUE, graphics library errors and notices will be posted. This
- // functionality will only work with the "debugging" version of QuickDraw GX.
- // If the debugging version is not installed, nothing bad will happen, but these
- // functions will not work.
-
- Boolean gDebugging = true;
-
- // Set "gGiveMeValidation" to TRUE if you want receive run-time validation.
-
- Boolean gGiveMeValidation = true;
-
-
- // gGraphicsHeapSize sets the size of the graphics heap created by calling the
- // GXNewGraphicsClient routine in main () within QuickDraw GX shell.c. You can determine
- // the amount of graphics heap required by using GraphicsBug. I'm giving it 600K,
- // since we need abunch if we have several windows open.
-
- long gGraphicsHeapSize = 600;
-
- // gOurPrintingOverrideUPP is a universal proc pointer for our printing event
- // override. This is so that our override can be native PowerPC code if necessary.
-
- GXPrintingEventUPP gOurPrintingOverrideUPP;
-
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoSetup()
- |**| Here's where we initialize any global variables our application needs.
- |**| We have only one at this time -- the universal proc pointer for
- |**| our printing override.
- |**| ---------------------------------------------------------------------
- \**/
- void DoSetup (void)
- { // Initialize our printing event override UPP
- gOurPrintingOverrideUPP = NewGXPrintingEventProc(MyPrintingEventOverride);
- }
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoDraw()
- |**| Draw the contents of the window. The first parameter is the window
- |**| to draw, and the second parameter is true if we're updating an existing
- |**| image. If that's the case, we should redraw the ampersand shape and not
- |**| change the oval shape any. If we do all our rotations and color
- |**| adjustments on update events, when the system sets the clipping to only
- |**| the update region, the window gets terribly befuddled. So, to counter
- |**| this, no changes are made to the shapes if we're updating, and we don't
- |**| erase the old shapes, but we _do_ draw the ampersand shape.
- |**| It sounds weird, but it works well. Try it.
- |**| ---------------------------------------------------------------------
- \**/
- void DoDraw(WindowPtr wind, Boolean updating)
- {
- gxShape eraseOval;
- gxShape drawOval;
- gxColor drawOvalColor;
- gxDashRecord ourDash;
- gxColor gColorWhite = xRGB (0xFFFF, 0xFFFF, 0xFFFF);
-
- // First, initialize our document variables.
-
- drawOval = GetDocOvalShape(wind);
- if (!updating)
- {
- (void *) GXGetShapeColor(drawOval, &drawOvalColor);
- (void *) GXGetShapeDash(drawOval, &ourDash);
-
- // Get the erasing oval from the document's structure.
- // Drawing this "erase oval" on a white background wipes out the last drawing of
- // the drawOval shape. We then cache it so we can draw it as fast as possible
- // later in this routine.
-
- eraseOval = GetDocEraseShape(wind); // get the erasing shape
- GXCopyToShape(eraseOval, drawOval); // copy drawOval's geometry to eraseOval
- GXSetShapeColor(eraseOval, &gColorWhite); // set eraseOval's color to white
- GXCacheShape(eraseOval); // make this draw faster below
-
- // We now can erase the last-drawn oval when we please by drawing eraseOval. Now,
- // we turn to drawing the next rotation of the drawOval. First, we increment the
- // hue by 1/32 (in fixed notation) and increment the dash's phase by the same amount
- // (but this time in fract notation).
-
- drawOvalColor.element.hsv.hue += fixed1/32;
- drawOvalColor.element.hsv.saturation += fixed1/24;
- drawOvalColor.element.hsv.value += fixed1/20;
- ourDash.phase += fract1/32;
-
- // To make the changes to ourDash and drawOvalColor take effect, we have to stuff
- // them back in the shape. Then we cache the drawOval shape so it will draw faster.
-
- GXSetShapeColor (drawOval, &drawOvalColor);
- GXSetShapeDash (drawOval, &ourDash);
- GXCacheShape (drawOval);
-
- // Guess what? GXGetShapeDash makes a copy of the dashing shape, so now we need
- // to dispose of it! (This wasn't obvious to me, and took me some time to figure
- // out, so I'm boring you with this interesting tidbit in revenge.)
-
- GXDisposeShape(ourDash.dash);
-
- }
-
- // Now we're ready to erase the old oval and draw the new one! If we're updating,
- // draw the ampersand as well.
-
- if (!updating)
- GXDrawShape(eraseOval);
- GXDrawShape (drawOval);
-
- }
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoCreateNew()
- |**| This routine is called when a window needs to be created.
- |**| ---------------------------------------------------------------------
- \**/
- OSErr DoCreateNew (void)
- {
- OSErr err = noErr;
- WindowPtr wind;
-
- // Get and create our window from the resource fork
-
- wind = GetNewWindow(rWindResource, nil, (WindowPtr)-1L);
-
- // Attach a default gxViewPort to it, create and iInitialize our
- // private data for it, and add a sample image to its page shape.
-
- if ( wind == NULL )
- return (MemError());
-
- GXIgnoreGraphicsNotice(transform_already_set);
- SetDefaultViewPort(GXNewWindowViewPort(wind));
- GXPopGraphicsNotice();
-
- err = DoWindowInit(wind);
- if ( err != noErr )
- return err;
-
- CreateSampleImage(wind);
- return err;
- }
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoDispose()
- |**| This routine is called when a window needs to be disposed of.
- |**| ---------------------------------------------------------------------
- \**/
- void DoDispose (WindowPtr wind)
- {
- TH_Doc doc;
-
- // You should always dispose of your GX graphics objects before tossing your window.
- // Why? It's generally good form and this approach guarantees that everything is
- // disposed. If you had not disposed of everything, the call to DisposeWindow should
- // dispose of the objects. If you are running the debugging version of QuickDraw GX
- // with notices set, you will receive a notice that you had not disposed of everything.
- // You can turn notices on in this file by setting gDebugging = TRUE (above).
-
- if ( wind != NULL )
- {
- doc = (TH_Doc)GetWRefCon(wind); // Remember, this is where we stored our private data.
- GXDisposeShape(GetDocOvalShape(wind)); // Dispose of this doc's oval.
- GXDisposeShape(GetDocEraseShape(wind)); // Dispose of this doc's erasing shape
- GXDisposeJob(GetDocJob(wind)); // Dispose of this doc's print job.
- DisposHandle((Handle) doc); // Dispose of our private data.
- DisposeWindow(wind); // Dispose of the window.
- }
- }
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoIdle()
- |**| This routine is called to do things while idling through the event loop.
- |**| ---------------------------------------------------------------------
- \**/
- void DoIdle (WindowPtr wind)
- {
- if ( wind != NULL )
- if ((((WindowPeek)wind)->windowKind == userKind) && (wind != nil))
- DoDraw(wind, false);
- }
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoTeardown()
- |**| This routine is called just before we quit to remove anything
- |**| persistent that might have been setup by DoSetup().
- |**| ---------------------------------------------------------------------
- \**/
- void DoTeardown (void)
- {
- DisposeRoutineDescriptor(gOurPrintingOverrideUPP);
- }
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoClick()
- |**| ---------------------------------------------------------------------
- \**/
- void DoClick(WindowPtr window, Point p)
- {
- }
-
-
-
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| DoWindowInit()
- |**| In this function we create and initialize the the private document
- |**| structure for a new window. This structure contains the print job and
- |**| the shape which is drawn in the window. We store this data in a handle
- |**| and hang it off the window's refCon field for easy retrieval. By doing
- |**| this, rather than using globals, we can create many windows containing
- |**| unique print jobs and shapes.
- |**| ---------------------------------------------------------------------
- \**/
- OSErr DoWindowInit (WindowPtr wind)
- {
- OSErr err = noErr;
- gxJob docJob;
- TH_Doc windDoc;
-
-
- // Create a print job for this document. This will be the same as the system default until
- // the user goes through the dialogs for Page Setup or Print…
-
- err = GXNewJob(&docJob);
-
-
- // If there are no errors, create a handle the size of our document structure and store
- // the print job in it. Store the handle in the window's refCon field so that we can
- // get at it. (Note that the utility routine "GetDocJob" can be used to do this easily.
-
- if ( err == noErr )
- {
- windDoc = (TH_Doc) NewHandleClear(sizeof(T_Doc));
-
- if ( windDoc == NULL )
- err = MemError();
- else
- {
- (*windDoc)->docJob = docJob;
- SetWRefCon(wind, (long) windDoc);
- }
-
- // Now install our application override for PrintingEvent so that we can
- // support the new movable-modal printing dialog boxes.
-
- GXInstallApplicationOverride(docJob, gxPrintingEvent, gOurPrintingOverrideUPP);
-
- }
-
- return err;
- }
-
-
- /**\
- |**| ---------------------------------------------------------------------
- |**| CreateSampleImage()
- |**| This function creates primitive shapes and adds them to the window's page shape.
- |**| ---------------------------------------------------------------------
- \**/
- void CreateSampleImage (WindowPtr wind)
- {
- Rect ourWindowRect = wind->portRect; // the rectangle for this window
- // in QuickDraw coordinates
- gxShape layout; // the layout shape we dash the oval with
- gxShape oval; // the oval that the layout lives in
- gxShape eraseOval; // another oval shape to erase with
- gxDashRecord ourDash; // the record for our complex dash
- gxColor ovalColor; // the color for the oval
- gxRectangle bounds; // the bounds of various shapes (reused)
- gxRectangle ourRectangle; // the rectangle for the oval's use
- gxRunControls runControls; // default run controls for layouts
- gxLayoutOptions layoutOptions; // default layout options for layouts
- char *textRuns[3]; // array of text runs for our dash layout
- gxStyle textStyles[3]; // array of styles for our dash layout
- short textLengths[3]; // array of lengths for our dash layout
- short totalLength; // total length of the text
- short level0 = 0; // variable for use with GXNewLayout
- char * text1 = "Aetna "; // text run #1
-
- // Text run #2 is "Arabic Macintosh" in Arabic:
- // meem, alif, kaf, noon, tah, wau, shin, <sp>, alif, lam, ein, reh, beh, yeh
-
- static char text2[] = {0xE5, 0xC7, 0xE3, 0xE6, 0xCA, 0xE8, 0xD4,
- 0x20, 0xC7, 0xE4, 0xD9, 0xD1, 0xC8, 0xEA, 0};
-
- char * text3 = " Office AWAY."; // text run #3
- gxPoint center; // center of all the graphics we do
-
-
- // Find the center of the window in fixed coordinates
-
- center.x = ff((ourWindowRect.right - ourWindowRect.left) / 2);
- center.y = ff((ourWindowRect.bottom - ourWindowRect.top) / 2);
-
- // Make a 270 x 270 gxRectangle centered in the window
-
- ourRectangle.top = center.y - ff(135);
- ourRectangle.left = center.x - ff(135);
- ourRectangle.bottom = center.y + ff(135);
- ourRectangle.right = center.x + ff(135);
-
- // Use ourRectangle to make an oval, and get it ready to be dashed.
-
- oval = NewOval(&ourRectangle);
- GXSetShapeFill(oval, gxClosedFrameFill);
- GXSetShapePen(oval, IntToFixed(14));
- (void *) SetCommonColor(&ovalColor, red);
- (void *) GXConvertColor(&ovalColor, gxHSVSpace, nil, nil); // convert to HSV
-
- // Copy the same oval to our eraseOval shape so we can use it later.
-
- eraseOval = GXNewShape(gxPathType);
- GXCopyToShape(eraseOval, oval);
-
- // Initialize the array of text runs for our layout shape
-
- textRuns[0] = text1;
- textRuns[1] = text2;
- textRuns[2] = text3;
-
- // Initialize the text lengths. MyStrLength is a function in this file.
-
- textLengths[0] = MyStrLength(text1);
- textLengths[1] = MyStrLength(text2);
- textLengths[2] = MyStrLength(text3);
-
- totalLength = textLengths[0] + textLengths[1] + textLengths[2];
-
- // Use library routines to initialize default gxLayoutOptions and gxRunControls structures
-
- InitializeLayoutOptions (&layoutOptions);
- InitializeRunControls (&runControls);
-
- // Use the library routines to initialize three style runs. The first one is 28-point
- // Helvetica. NewLayoutStyle is found in layout library.c.
-
- textStyles[0] = NewLayoutStyle(
- (char *) "\pHoefler Text", // the gxFontName for the style
- ff(28), // the point size in fixed point
- 0, // gxTextAttributes (none)
- &runControls, // our default run controls
- nil, // run features (none for us)
- 0, // count of run features
- nil); // style run overrides (none for us)
-
- // The second one is 28-point Baghdad.
-
- textStyles[1] = NewLayoutStyle(
- (char *) "\pBaghdad Plain", // the gxFontName for the style
- ff(28), // the point size in fixed format
- 0, // gxTextAttributes (none)
- &runControls, // our default run controls
- nil, // run featuers (none for this style)
- 0, // count of run features
- nil); // style run overrides (none for us)
-
- // The third and final one is 28-point Times Roman
-
- textStyles[2] = NewLayoutStyle(
- (char *) "\pHoefler Text Italic",// the gxFontName for this style
- ff(28), // the point size (fixed format)
- 0, // no gxTextAttributes
- &runControls, // our default run controls
- nil, // no run features
- 0, // count of no run features = 0
- nil); // style run overrides (still none)
-
- // We're ready to build our layout now!
-
- layout = GXNewLayout(
- 3, // count of text runs
- textLengths, // array of lengths of each run
- (void *)textRuns, // array of pointers to the text
- 3, // count of style runs
- textLengths, // array of the byte lengths of each run
- textStyles, // array of the styles
- 1, // number of levels in the layout
- &totalLength, // array of lengths of levels (only one)
- &level0, // array of the levels (only one)
- &layoutOptions, // options (default)
- nil); // position of the layout shape (none)
-
- GXSetShapeColor(layout, &ovalColor);
-
- // Now we get the bounds of the layout shape to determine how to proceed with the dashing.
- // Why are we using GXGetShapeBounds instead of GXGetShapeTypographicBounds? The latter
- // does not include the size of any hanging punctuation in the width; the former does.
- // Since we're only interested in the width this time, that's the call we want.
-
- (void) GXGetShapeBounds (layout, 0, &bounds);
-
- // Changing the shape to a path type will make dashing it faster. We could also call
- // GXPrimitiveShape twice to do this (the first time makes a glyph shape).
-
- GXSetShapeType(layout, gxPathType);
-
- // We're ready to use the layout/path shape as the dash shape for our oval.
- // Initialize our dash record and use it!
-
- ourDash.attributes =
- gxAutoAdvanceDash | gxBreakDash; // use whole multiples of dash shapes
- ourDash.dash = layout; // the shape to dash with
- ourDash.phase = 0; // the initial phase
- ourDash.advance = bounds.right + ff(10); // the advance (shape size + 10 pixels)
- ourDash.scale = IntToFixed(14); // the scale perpendicular to contour
-
- GXSetShapeDash (oval, &ourDash);
-
- // Now scale the oval shape to fill the window.
-
- GXScaleShape(
- oval, // the shape to get the transform from
- (fixed)0x00016000, // scale it horizontally by 1 3/8
- (fixed)0x00016000, // and vertically by 1 3/8
- center.x, // about the center of the rectangle
- center.y); // as previously determined
-
-
- // Save the layout and ampersand shapes for this window in the doc structure
- // attached to this document.
-
- {
-
- TH_Doc windDoc; // the document structure
-
- windDoc = (TH_Doc) GetWRefCon(wind);
- (*windDoc)->docOval = oval;
- (*windDoc)->eraseOval = eraseOval;
-
- }
-
-
- // Dispose of all things we allocated in here that we don't need to keep.
-
- GXDisposeShape(layout);
- GXDisposeStyle (textStyles[0]);
- GXDisposeStyle (textStyles[1]);
- GXDisposeStyle (textStyles[2]);
-
-
- // Invalidate the window's portRect so that everything gets updated.
-
- SetPort(wind);
- InvalRect(&ourWindowRect);
- }
-